import Foundation
import UIKit
import CoreImage

/// Errors that can occur during file management operations
enum ImageFileManagerError: Error {
    case conversionFailed
    case saveFailed(String)
    case loadFailed(String)
    case deleteFailed(String)
}

/// Manages file operations for images in the photo editing app
class ImageFileManager {
    // Singleton instance
    static let shared = ImageFileManager()
    
    // Private initializer to prevent multiple instances
    private init() {}
    
    // Directories
    private lazy var documentsDirectory: URL = {
        FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
    }()
    
    private lazy var editedImagesDirectory: URL = {
        let url = documentsDirectory.appendingPathComponent("EditedImages", isDirectory: true)
        
        // Create directory if it doesn't exist
        if !FileManager.default.fileExists(atPath: url.path) {
            do {
                try FileManager.default.createDirectory(at: url, withIntermediateDirectories: true)
            } catch {
                print("Failed to create EditedImages directory: \(error)")
            }
        }
        
        return url
    }()
    
    /// Save an edited image
    /// - Parameters:
    ///   - image: UIImage to save
    ///   - originalFileName: Optional original filename
    /// - Returns: Result with saved file URL or error
    func saveEditedImage(_ image: UIImage, originalFileName: String? = nil) -> Result<URL, ImageFileManagerError> {
        // Generate unique filename
        let fileName = originalFileName ?? generateUniqueFileName()
        let fileURL = editedImagesDirectory.appendingPathComponent(fileName)
        
        guard let data = image.jpegData(compressionQuality: 0.8) else {
            return .failure(.conversionFailed)
        }
        
        do {
            try data.write(to: fileURL)
            return .success(fileURL)
        } catch {
            return .failure(.saveFailed(error.localizedDescription))
        }
    }
    
    /// Load an edited image
    /// - Parameter fileName: Name of the image file
    /// - Returns: Result with UIImage or error
    func loadEditedImage(named fileName: String) -> Result<UIImage, ImageFileManagerError> {
        let fileURL = editedImagesDirectory.appendingPathComponent(fileName)
        
        do {
            let imageData = try Data(contentsOf: fileURL)
            guard let image = UIImage(data: imageData) else {
                return .failure(.loadFailed("Could not create UIImage"))
            }
            return .success(image)
        } catch {
            return .failure(.loadFailed(error.localizedDescription))
        }
    }
    
    /// Delete an edited image
    /// - Parameter fileName: Name of the image file to delete
    /// - Returns: Result indicating success or failure
    func deleteEditedImage(named fileName: String) -> Result<Void, ImageFileManagerError> {
        let fileURL = editedImagesDirectory.appendingPathComponent(fileName)
        
        do {
            try FileManager.default.removeItem(at: fileURL)
            return .success(())
        } catch {
            return .failure(.deleteFailed(error.localizedDescription))
        }
    }
    
    /// Generate a unique filename
    /// - Parameters:
    ///   - prefix: Filename prefix
    ///   - extension: File extension
    /// - Returns: Unique filename string
    func generateUniqueFileName(prefix: String = "edited", extension: String = "jpg") -> String {
        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = "yyyyMMdd_HHmmss_SSS"
        let timestamp = dateFormatter.string(from: Date())
        return "\(prefix)_\(timestamp).\(`extension`)"
    }
    
    /// List all edited images
    /// - Returns: Array of filenames
    func listEditedImages() -> [String] {
        do {
            return try FileManager.default.contentsOfDirectory(
                at: editedImagesDirectory, 
                includingPropertiesForKeys: nil
            )
            .filter { $0.pathExtension.lowercased() == "jpg" || $0.pathExtension.lowercased() == "jpeg" }
            .map { $0.lastPathComponent }
        } catch {
            print("Error listing edited images: \(error)")
            return []
        }
    }
    
    /// Get file size for a specific image
    /// - Parameter fileName: Name of the image file
    /// - Returns: File size in bytes, or nil if error occurs
    func getFileSize(for fileName: String) -> Int64? {
        let fileURL = editedImagesDirectory.appendingPathComponent(fileName)
        
        do {
            let attributes = try FileManager.default.attributesOfItem(atPath: fileURL.path)
            return attributes[.size] as? Int64
        } catch {
            print("Error getting file size: \(error)")
            return nil
        }
    }
    
    /// Export image to camera roll
    /// - Parameters:
    ///   - image: UIImage to export
    ///   - completion: Closure called with export result
    func exportToCameraRoll(_ image: UIImage, completion: @escaping (Bool) -> Void) {
        UIImageWriteToSavedPhotosAlbum(image, self, #selector(image(_:didFinishSavingWithError:contextInfo:)), nil)
    }
    
    /// Callback for image save to camera roll
    @objc private func image(_ image: UIImage, didFinishSavingWithError error: Error?, contextInfo: UnsafeRawPointer) {
        let success = error == nil
        print(success ? "Image saved successfully" : "Error saving image: \(error?.localizedDescription ?? "")")
    }
}

// MARK: - Image Metadata
extension ImageFileManager {
    /// Metadata for an image file
    struct ImageMetadata {
        let fileName: String
        let fileSize: Int64
        let creationDate: Date
        let lastModifiedDate: Date
    }
    
    /// Retrieve metadata for a specific image
    /// - Parameter fileName: Name of the image file
    /// - Returns: ImageMetadata or nil if retrieval fails
    func getImageMetadata(for fileName: String) -> ImageMetadata? {
        let fileURL = editedImagesDirectory.appendingPathComponent(fileName)
        
        do {
            let attributes = try FileManager.default.attributesOfItem(atPath: fileURL.path)
            
            return ImageMetadata(
                fileName: fileName,
                fileSize: attributes[.size] as? Int64 ?? 0,
                creationDate: attributes[.creationDate] as? Date ?? Date(),
                lastModifiedDate: attributes[.modificationDate] as? Date ?? Date()
            )
        } catch {
            print("Error retrieving image metadata: \(error)")
            return nil
        }
    }
}
